using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using System.ComponentModel.DataAnnotations;

namespace JGSY.CMS.LowCode.Platform.Controllers
{
    /// <summary>
    /// 团队管理控制器
    /// 提供团队的增删改查、成员管理、权限配置等功能的 RESTful API
    /// </summary>
    /// <remarks>
    /// 该控制器提供以下功能：
    /// - 团队的完整CRUD操作
    /// - 分页查询和条件筛选
    /// - 团队成员管理
    /// - 团队权限和状态控制
    /// - 批量操作支持
    /// 
    /// 所有接口都需要用户身份验证，部分接口需要特定权限
    /// </remarks>
    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    [Produces("application/json")]
    public class TeamsController : ControllerBase
    {
        private readonly ITeamAppService _teamService;
        private readonly ITeamMemberAppService _memberService;
        private readonly ILogger<TeamsController> _logger;

        /// <summary>
        /// 初始化团队控制器
        /// </summary>
        /// <param name="teamService">团队应用服务</param>
        /// <param name="memberService">团队成员应用服务</param>
        /// <param name="logger">日志记录器</param>
        public TeamsController(
            ITeamAppService teamService,
            ITeamMemberAppService memberService,
            ILogger<TeamsController> logger)
        {
            _teamService = teamService ?? throw new ArgumentNullException(nameof(teamService));
            _memberService = memberService ?? throw new ArgumentNullException(nameof(memberService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 分页查询团队列表
        /// </summary>
        /// <param name="pageIndex">页码，从1开始</param>
        /// <param name="pageSize">每页大小，默认20条</param>
        /// <param name="keyword">搜索关键字，支持团队名称和代码模糊匹配</param>
        /// <param name="departmentId">部门ID筛选</param>
        /// <param name="teamType">团队类型筛选</param>
        /// <param name="status">状态筛选</param>
        /// <returns>分页的团队列表</returns>
        /// <response code="200">查询成功，返回团队列表数据</response>
        /// <response code="400">参数错误或查询失败</response>
        /// <response code="401">未授权，需要登录</response>
        /// <response code="403">权限不足</response>
        [HttpGet]
        [ProducesResponseType(typeof(PagedResultDto<TeamDto>), 200)]
        [ProducesResponseType(typeof(object), 400)]
        [ProducesResponseType(401)]
        [ProducesResponseType(403)]
        public async Task<ActionResult<PagedResultDto<TeamDto>>> GetPaged(
            [FromQuery, Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")] int pageIndex = 1,
            [FromQuery, Range(1, 100, ErrorMessage = "每页大小必须在1-100之间")] int pageSize = 20,
            [FromQuery, StringLength(100, ErrorMessage = "搜索关键字长度不能超过100个字符")] string? keyword = null,
            [FromQuery] long? departmentId = null,
            [FromQuery, StringLength(50, ErrorMessage = "团队类型长度不能超过50个字符")] string? teamType = null,
            [FromQuery] byte? status = null)
        {
            try
            {
                _logger.LogInformation("分页查询团队列表，页码: {PageIndex}，页大小: {PageSize}", pageIndex, pageSize);

                var (items, total) = await _teamService.GetPagedAsync(pageIndex, pageSize, keyword, departmentId, teamType, status);
                var result = new PagedResultDto<TeamDto>(items, total, pageIndex, pageSize);

                _logger.LogInformation("成功返回团队列表，共 {Total} 条记录", total);
                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分页查询团队列表失败");
                return BadRequest(new { message = ex.Message });
            }
        }

        /// <summary>
        /// 获取所有团队列表
        /// </summary>
        /// <returns>所有团队的完整列表</returns>
        /// <response code="200">查询成功，返回团队列表</response>
        /// <response code="400">查询失败</response>
        /// <response code="401">未授权，需要登录</response>
        /// <remarks>
        /// 该接口返回所有可访问的团队，不进行分页。
        /// 适用于下拉框选择等场景，数据量较大时建议使用分页接口。
        /// </remarks>
        [HttpGet("all")]
        [ProducesResponseType(typeof(IEnumerable<TeamDto>), 200)]
        [ProducesResponseType(typeof(object), 400)]
        [ProducesResponseType(401)]
        public async Task<ActionResult<IEnumerable<TeamDto>>> GetAll()
        {
            try
            {
                _logger.LogInformation("获取所有团队列表");

                var items = await _teamService.GetAllAsync();
                
                _logger.LogInformation("成功获取所有团队列表，共 {Count} 个团队", ((List<TeamDto>)items).Count);
                return Ok(items);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取所有团队列表失败");
                return BadRequest(new { message = ex.Message });
            }
        }

        /// <summary>
        /// 根据ID获取团队详情
        /// </summary>
        /// <param name="id">团队唯一标识符</param>
        /// <returns>团队详细信息</returns>
        /// <response code="200">查询成功，返回团队详情</response>
        /// <response code="404">团队不存在</response>
        /// <response code="401">未授权，需要登录</response>
        /// <response code="403">权限不足</response>
        [HttpGet("{id:long}")]
        [ProducesResponseType(typeof(TeamDto), 200)]
        [ProducesResponseType(404)]
        [ProducesResponseType(401)]
        [ProducesResponseType(403)]
        public async Task<ActionResult<TeamDto>> GetById(long id)
        {
            try
            {
                var item = await _teamService.GetByIdAsync(id);
                if (item == null) return NotFound();
                return Ok(item);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting team {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("code/{code}")]
        [ProducesResponseType(200)]
        [ProducesResponseType(404)]
        public async Task<ActionResult<TeamDto>> GetByCode(string code)
        {
            try
            {
                var item = await _teamService.GetByCodeAsync(code);
                if (item == null) return NotFound();
                return Ok(item);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting team by code {Code}", code);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("department/{departmentId:long}")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<IEnumerable<TeamDto>>> GetByDepartment(long departmentId)
        {
            try
            {
                var items = await _teamService.GetByDepartmentAsync(departmentId);
                return Ok(items);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting teams by department {DepartmentId}", departmentId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("user/{userId:long}")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<IEnumerable<TeamDto>>> GetUserTeams(long userId)
        {
            try
            {
                var items = await _teamService.GetUserTeamsAsync(userId);
                return Ok(items);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting user teams {UserId}", userId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("{id:long}/stats")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> GetStats(long id, [FromQuery] DateTime? startDate = null, [FromQuery] DateTime? endDate = null)
        {
            try
            {
                var stats = await _teamService.GetTeamPerformanceAsync(id, startDate, endDate);
                return Ok(stats);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting team performance {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("search")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<PagedResultDto<TeamDto>>> Search([FromQuery] string keyword, [FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 20)
        {
            try
            {
                var (items, total) = await _teamService.SearchAsync(keyword, pageIndex, pageSize);
                return Ok(new PagedResultDto<TeamDto>(items, total, pageIndex, pageSize));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error searching teams");
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost]
        [ProducesResponseType(201)]
        [ProducesResponseType(400)]
        public async Task<ActionResult<TeamDto>> Create([FromBody] TeamDto dto)
        {
            try
            {
                var created = await _teamService.CreateAsync(dto);
                return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating team");
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPut("{id:long}")]
        [ProducesResponseType(200)]
        [ProducesResponseType(400)]
        public async Task<ActionResult<TeamDto>> Update(long id, [FromBody] TeamDto dto)
        {
            try
            {
                dto.Id = id;
                var updated = await _teamService.UpdateAsync(dto);
                return Ok(updated);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating team {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpDelete("{id:long}")]
        [ProducesResponseType(200)]
        [ProducesResponseType(404)]
        public async Task<ActionResult<object>> Delete(long id)
        {
            try
            {
                var ok = await _teamService.DeleteAsync(id);
                if (!ok) return NotFound();
                return Ok(new { success = true });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting team {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost("batch-delete")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> BatchDelete([FromBody] BatchDeleteRequest request)
        {
            try
            {
                var count = await _teamService.BatchDeleteAsync(request.Ids);
                return Ok(new { success = true, count });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error batch deleting teams");
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost("{id:long}/status")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> UpdateStatus(long id, [FromQuery] byte status)
        {
            try
            {
                var ok = await _teamService.UpdateStatusAsync(id, status);
                return Ok(new { success = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating team status {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost("{id:long}/leader")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> SetLeader(long id, [FromQuery] long? leaderId)
        {
            try
            {
                var ok = await _teamService.SetLeaderAsync(id, leaderId);
                return Ok(new { success = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error setting team leader {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost("{id:long}/transfer-department")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> TransferDepartment(long id, [FromQuery] long newDepartmentId)
        {
            try
            {
                var ok = await _teamService.TransferToDepartmentAsync(id, newDepartmentId);
                return Ok(new { success = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error transferring team department {Id}", id);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("{teamId:long}/members")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<List<TeamMemberDto>>> GetMembers(long teamId)
        {
            try
            {
                var items = await _memberService.GetByTeamIdAsync(teamId);
                return Ok(items);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting team members {TeamId}", teamId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost("{teamId:long}/members")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> AddMember(long teamId, [FromQuery] long userId, [FromQuery] string? role = null)
        {
            try
            {
                var ok = await _teamService.AddMemberAsync(teamId, userId, role);
                return Ok(new { success = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error adding member to team {TeamId}", teamId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpDelete("{teamId:long}/members/{userId:long}")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> RemoveMember(long teamId, long userId)
        {
            try
            {
                var ok = await _teamService.RemoveMemberAsync(teamId, userId);
                return Ok(new { success = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error removing member from team {TeamId}", teamId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpPost("{teamId:long}/members/role")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> UpdateMemberRole(long teamId, [FromQuery] long userId, [FromQuery] string role)
        {
            try
            {
                var ok = await _teamService.UpdateMemberRoleAsync(teamId, userId, role);
                return Ok(new { success = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating member role {TeamId}", teamId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("{teamId:long}/members/is-member")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> IsMember(long teamId, [FromQuery] long userId)
        {
            try
            {
                var ok = await _teamService.IsMemberAsync(teamId, userId);
                return Ok(new { isMember = ok });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking is member {TeamId}", teamId);
                return BadRequest(new { message = ex.Message });
            }
        }

        [HttpGet("code-exists")]
        [ProducesResponseType(200)]
        public async Task<ActionResult<object>> CodeExists([FromQuery] string code, [FromQuery] long? excludeId = null)
        {
            try
            {
                var exists = await _teamService.CodeExistsAsync(code, excludeId);
                return Ok(new { exists });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking code exists {Code}", code);
                return BadRequest(new { message = ex.Message });
            }
        }
    }
}
